package b1w1nn1ng.crossf1t.business;

import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.math.*;
import java.security.*;

import b1w1nn1ng.crossf1t.db.Database;

public class User {
	//Fields for one user--feel free to add more if you need them.
	private String username;
	private String password;
	private String email;
	private String firstName;
	private String lastName;
	private String question;
	private String answer;
	private int friendCode;
	private int id;
	private ArrayList<Integer> friends;//holds the ID's of the user's friends
	private ArrayList<String> goals;
	boolean receiveReport = false;
	private int height, weight;//in inches and pounds.
	private int numWorkouts = 0;

	public User() {
		return;
	}
	
	
	/**
	 * This is the constructor that most everyone will be using because it does not allow you to specify an id, the id will be added by the database
	 * @param username
	 * @param password
	 * @param email
	 * @param firstName
	 * @param lastName
	 * @param question
	 * @param answer
	 * @param friendCode
	 * @param id
	 */
	public User(String username, String password, String email, String firstName,
			String lastName, String question, String answer, int weight, int height) {
		this.username=username;
		this.password=password;
		this.email = email;
		this.firstName = firstName;
		this.lastName = lastName;
		this.question = question;
		this.answer = answer;
		//this.friendCode undefined right now
		this.weight = weight;
		this.height = height;
		friends = new ArrayList<Integer>();
	}
	
	/**
	 * This constructor which uses the id parameter is ONLY TO BE CALLED BY THE DATABASE METHODS WHICH RETURN A USER OBJECT!!!! Otherwise you will explode the database.
	 * @param username
	 * @param password
	 * @param email
	 * @param firstName
	 * @param lastName
	 * @param question
	 * @param answer
	 * @param friendCode
	 * @param id
	 */
	public User(String username, String password, String email, String firstName,
			String lastName, String question, String answer, int friendCode,int id,
			int weight, int height, ArrayList<Integer> friendArrayList, ArrayList<String> goals) {
		this.username=username;
		this.password=password;
		this.email = email;
		this.firstName = firstName;
		this.lastName = lastName;
		this.question = question;
		this.answer = answer;
		this.friendCode = friendCode;
		this.id = id;
		this.weight = weight;
		this.height = height;
		this.friends = friendArrayList;
		this.goals = goals;
		
	}
	
	public void addGoal(String g)
	{
		goals.add(g.trim());
		
		try {
			Database.addGoal(id,g);
		} catch (SQLException e) {
			System.out.println("SQLException in addGoal");			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			System.out.println("ClassNotFoundException in addGoal");
			e.printStackTrace();
		}
		//addGoal will add a goal(int,string,boolean) to the database.
		//id is the user id, goal is the goal's name, on is whether it should be "On" or "Off"
	}
	
	public void deleteGoal(String g)
	{
		goals.remove(g.trim());
		try {
			Database.removeGoal(id,g);
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public boolean updateFriendList() throws SQLException, ClassNotFoundException
	{
		//give id of user and friend list to database to 
		return Database.updateFriendList(id, friends);
	}
	
	public void setReceiveReport(boolean receive)
	{
		receiveReport = receive;
	}

	public double calculateBMI()
	{
		double temp= weight*703.0/Math.pow(height, 2);
		try{
			DecimalFormat format = new DecimalFormat("###.##");
			return Double.valueOf(format.format(temp));
		}
		catch (Exception e){
			/*temp *= 100;
			int temp2 = (int) temp;
			temp = (double) temp2;
			temp /= 100;
			return temp;*/
		}
		return temp;
	}
	
	/**
	 * 
	 * @param username - username of friend to add
	 * @return
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public boolean addFriend(String username) throws SQLException, ClassNotFoundException
	{
		System.out.println("inside addfriend method username: " + username);
		User user = Database.getUserByUsername(username);
		int id = user.getId();
		//you already have the friend in your list
		if(friends.contains(id))
		{
			return false;
		}
		
		
		friends.add(id);
		this.updateFriendList();
		return true;
	}

	public boolean removeFriend(String username) throws SQLException, ClassNotFoundException
	{
		//get the user corresponding to the parameter username
		User user = Database.getUserByUsername(username);
		int id = Database.getIdByUsername(username);
		//you don't have the friend in your list
		if(!friends.contains(id))
		{
			return false;
		}

		user.friends.remove(this.id);
		user.updateFriendList();
		friends.remove(id);
		this.updateFriendList();
		return true;
	}

	public void update() throws SQLException, ClassNotFoundException
	{
		Database.updateUser(this);
	}

	public ArrayList<String> getGoals() {
		return goals;
	}

	public void setGoals(ArrayList<String> goals) {
		this.goals = goals;
	}
	
	public ArrayList<Integer> getFriends()
	{
		return friends;
	}
	
	public void setFriends(ArrayList<Integer> friends)
	{
		this.friends = friends;
	}
	
	public String getUsername() {
		return this.username;
	}
	public void setUsername(String username) {
		this.username = username;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		
		this.password = password;

		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {

			e.printStackTrace();
		}
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public String getQuestion() {
		return question;
	}
	public void setQuestion(String question) {
		this.question = question;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	public String getAnswer() {
		return answer;
	}
	public void setAnswer(String answer) {
		this.answer = answer;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public int getFriendCode() {
		return this.friendCode;
	}

	public void setFriendCode(int friendCode) {
		this.friendCode = friendCode;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	public int getHeight() {
		return height;
	}


	public void setHeight(int height) {
		this.height = height;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}


	public int getWeight() {
		return weight;
	}


	public void setWeight(int weight) {
		this.weight = weight;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}


	public boolean equals(Object o){
		if(!(o instanceof User))
				return false;
		User user = (User)o;
				
		return this.username.equals(user.getUsername()) && 
				this.firstName.equals(user.getFirstName()) &&
				this.lastName.equals(user.getLastName()) &&
				this.email.equals(user.getEmail()) &&
				this.question.equals(user.getQuestion()) &&
				this.answer.equals(user.getAnswer()) &&
				this.friendCode == user.getFriendCode() &&
				this.id == user.getId();
	}


	public void setNumWorkouts(int numWorkouts) {
		this.numWorkouts = numWorkouts;
		try {
			this.update();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}


	public int getNumWorkouts() {
		return this.numWorkouts;
	}

		
	public static User getUserByUsername (String username) throws SQLException, ClassNotFoundException {
		
		if (!Database.isUsername(username))
			return null;
		User user = Database.getUserByUsername(username);
		return user;
	}
	
	public static User getUserByFriendCode(int friendCode) throws SQLException, ClassNotFoundException
	{
		try {
			return Database.getUserByFriendCode(friendCode);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public boolean hasWorkout(Calendar date) throws SQLException, ClassNotFoundException{
		//return Database.getWorkout(this.id, date) !=null;
		//TODO uncomment above code
		//return date.get(Calendar.DATE) % 3 == 0;
		return (Math.random()>.6);
	}
	public static User getUserById(int id) throws SQLException, ClassNotFoundException{
		return Database.getUserByID(id);
	}
	
	/**
	 * THIS METHOD IS FOR TESTING PURPOSES ONLY
	 * RETURNS a complete user object 
	 */
	public static User getTestUSER(){
		
		String username = "Doooooooom1337";
		String password = "oren1";
		String email = "email@email.com";
		String firstName = "Oren";
		String lastName = "Radousky";
		String question = "How awesome is this project";
		String answer = "so awesome";
		int friendCode = 55975;
		int id = 65;
		ArrayList<Integer> friends = new ArrayList<Integer>() ; //holds the ID's of the user's friends
		friends.add(11111); friends.add(22222); friends.add(33333); friends.add(44444); friends.add(55555);
		ArrayList<String> goals = new ArrayList<String>();
		
		boolean receiveReport = false;
		 int height = 67, weight = 500;//in inches and pounds.
		 int numWorkouts = 445;
		User user = new User( username,  password,  email,  firstName,
				 lastName,  question,  answer,  friendCode, id,
				 weight,  height, friends, goals );
		System.out.println(user.getFriendCode());
		user.setNumWorkouts(numWorkouts);
		user.setGoals(goals);
		return user;
	}
	
	public static boolean verifyLogin(String username, String password){
		
		try {
			
////			-------------------------------------------------------------
			 MessageDigest pass = MessageDigest.getInstance("MD5");
			 pass.update(password.getBytes(),0,password.length());
			 String REALDEAL = new BigInteger(1, pass.digest()).toString(16);
			 System.out.println(REALDEAL);
////			-------------------------------------------------------
//			
//			System.out.println("Username: " + username + " Password: " + password);
//			System.out.println("Username: " + verifyUser.getUsername() + " Password: " + verifyUser.getPassword());
//			//return (verifyUser.getPassword()).equals(md5);
			 User verifyUser = Database.getUserByUsername(username);
			return verifyUser.getPassword().equals(REALDEAL);
		} catch (Exception e){
			
		}
		return false;
	}

}
